home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 32 / advsys.zip / ADVCOM.C < prev    next >
Text File  |  1987-06-28  |  15KB  |  635 lines

  1. /* advcom.c - a compiler for adventure games */
  2. /*
  3.     Copyright (c) 1986, by David Michael Betz
  4.     All rights reserved
  5. */
  6.  
  7. #include "advcom.h"
  8. #include "advavl.h"
  9. #include "advdbs.h"
  10.  
  11. #define BANNER \
  12. "ADVCOM v1.2a - Copyright (c) 1987, by David Betz"
  13.  
  14. /* symbol tables */
  15. SYMBOL *symbols;
  16. ARGUMENT *arguments;
  17. ARGUMENT *temporaries;
  18.  
  19. /* adventure id information */
  20. char aname[19];
  21. int aversion;
  22.  
  23. /* word table */
  24. int wtable[WMAX+1],wcnt;
  25.  
  26. /* object table */
  27. int otable[OMAX+1],ocnt;
  28.  
  29. /* action table */
  30. int atable[AMAX+1],acnt;
  31.  
  32. /* constant, variable and property symbol counts */
  33. int ccnt,vcnt,pcnt;
  34.  
  35. /* data and code space */
  36. char *data,*code;
  37. int dptr,cptr;
  38.  
  39. /* buffer for building an object */
  40. int objbuf[OSIZE];
  41. int nprops;
  42.  
  43. /* global variables */
  44. char ifile[FMAX];    /* input file name */
  45. char ofile[FMAX];    /* output file name */
  46. FILE *ifp;        /* input file pointer */
  47. unsigned int msgoff;    /* message section offset */
  48. TREE *words;        /* word tree */
  49. int curwrd;        /* current word number */
  50. int curobj;        /* current object */
  51. int curact;        /* current action */
  52. int def_flag;        /* default action flag value */
  53. int def_mask;        /* default action mask value */
  54.  
  55. /* header information variables */
  56. int h_init;        /* initialization code */
  57. int h_update;        /* update code */
  58. int h_before;        /* before handler code */
  59. int h_after;        /* after handler code */
  60. int h_error;        /* error handling code */
  61.  
  62. /* external routines */
  63. extern char *malloc();
  64. extern char *calloc();
  65. extern TREE *tnew();
  66.  
  67. /* external variables */
  68. extern int errcount;    /* error count */
  69. extern int t_value;    /* token value */
  70. extern char t_token[];    /* token string */
  71. extern char *t_names[];    /* token names */
  72. extern long ad_foff;    /* data file offset */
  73.  
  74. /* forward declarations */
  75. SYMBOL *sfind();
  76. SYMBOL *senter();
  77. char *save();
  78.  
  79. /* main - the main routine */
  80. main(argc,argv)
  81.   int argc; char *argv[];
  82. {
  83.     int tkn,obj,i;
  84.  
  85.     /* initialize */
  86.     advinit(BANNER,argc,argv,ifile,ofile);
  87.     wcnt = ocnt = acnt = ccnt = vcnt = pcnt = msgoff = 0;
  88.     symbols = NULL; arguments = temporaries = NULL;
  89.     h_init = h_update = h_before = h_after = h_error = NIL;
  90.     def_flag = def_mask = 0;
  91.     aname[0] = 0;
  92.     sinit();
  93.  
  94.     /* setup the code and data space */
  95.     if ((data = calloc(1,DMAX)) == 0)
  96.     advfatal("insufficient memory");
  97.     if ((code = calloc(1,CMAX)) == 0)
  98.     advfatal("insufficient memory");
  99.     dptr = cptr = 1;    /* make sure nothing has a zero offset */
  100.  
  101.     /* open the input file */
  102.     if ((ifp = fopen(ifile,"r")) == NULL)
  103.     advfatal("can't open input file");
  104.  
  105.     /* create and initialize the output file */
  106.     ad_create(ofile);
  107.     for (i = 0; i++ < 512; ad_putc('\0'))
  108.     ;
  109.  
  110.     /* create the word tree */
  111.     words = tnew();
  112.  
  113.     /* enter builtin constants */
  114.     center("t",-1);
  115.     center("nil",0);
  116.  
  117.     /* enter the builtin variables */
  118.     venter("$actor");
  119.     venter("$action");
  120.     venter("$dobject");
  121.     venter("$ndobjects");
  122.     venter("$iobject");
  123.     venter("$ocount");
  124.  
  125.     /* enter the preposition "to" */
  126.     add_word("to",WT_PREPOSITION);
  127.  
  128.     /* process statements until end of file */
  129.     while ((tkn = token()) == T_OPEN) {
  130.     frequire(T_IDENTIFIER);
  131.  
  132.     /* identification statement */
  133.     if (match("adventure"))
  134.         do_adventure();
  135.  
  136.     /* vocabulary statements */
  137.     else if (match("adjective"))
  138.         do_word(WT_ADJECTIVE);
  139.     else if (match("preposition"))
  140.         do_word(WT_PREPOSITION);
  141.     else if (match("conjunction"))
  142.         do_word(WT_CONJUNCTION);
  143.     else if (match("article"))
  144.         do_word(WT_ARTICLE);
  145.     else if (match("synonym"))
  146.         do_synonym();
  147.  
  148.     /* constant, variable, function and default definition statements */
  149.     else if (match("define"))
  150.         do_define();
  151.     else if (match("variable"))
  152.         do_variable();
  153.     else if (match("default"))
  154.         do_default();
  155.  
  156.     /* property definition statement */
  157.     else if (match("property"))
  158.         do_defproperty();
  159.  
  160.     /* handle the init, before and after code statements */
  161.     else if (match("init"))
  162.         h_init = do_code(t_token);
  163.     else if (match("update"))
  164.         h_update = do_code(t_token);
  165.     else if (match("before"))
  166.         h_before = do_code(t_token);
  167.     else if (match("after"))
  168.         h_after = do_code(t_token);
  169.     else if (match("error"))
  170.         h_error = do_code(t_token);
  171.  
  172.     /* action definition statement */
  173.     else if (match("action"))
  174.         do_action();
  175.  
  176.     /* object definition statements */
  177.         else if (match("object"))
  178.         do_object(t_token,NIL);
  179.  
  180.     /* object instance definition statements */
  181.     else if (obj = ofind(t_token))
  182.         do_object(t_token,obj);
  183.  
  184.     /* error, unknown statement */
  185.     else
  186.         error("Unknown statement type");
  187.     }
  188.     require(tkn,T_EOF);
  189.  
  190.     /* close the input file */
  191.     fclose(ifp);
  192.  
  193.     /* output the data structures */
  194.     output();
  195.  
  196.     /* close the output file */
  197.     ad_close();
  198. }
  199.  
  200. /* getvalue - get a value */
  201. int getvalue()
  202. {
  203.     SYMBOL *sym;
  204.  
  205.     switch (token()) {
  206.     case T_IDENTIFIER:    if (sym = sfind(t_token))
  207.                 return (sym->s_value);
  208.             return (oenter(t_token));
  209.     case T_NUMBER:    return (t_value);
  210.     case T_STRING:    return (t_value);
  211.     default:        error("Expecting identifier, number or string");
  212.             return (0);
  213.     }
  214. }
  215.  
  216. /* dalloc - allocate data space */
  217. int dalloc(size)
  218.   int size;
  219. {
  220.     if ((dptr += size) > DMAX)
  221.     advfatal("out of data space");
  222.     return (dptr - size);
  223. }
  224.  
  225. /* add_word - add a word to the dictionary */
  226. int add_word(str,type)
  227.   char *str; int type;
  228. {
  229.     if ((curwrd = tfind(words,str)) == NIL) {
  230.     if (wcnt < WMAX) {
  231.         curwrd = ++wcnt;
  232.         wtable[curwrd] = type;
  233.         tenter(words,str);
  234.     }
  235.     else {
  236.         error("too many words");
  237.         curwrd = 0;
  238.     }
  239.     }
  240.     else if (wtable[curwrd] == WT_UNKNOWN)
  241.     wtable[curwrd] = type;
  242.     else if (type != WT_UNKNOWN && type != wtable[curwrd])
  243.     error("Ambiguous word type");
  244.     return (curwrd);
  245. }
  246.  
  247. /* add_synonym - add a synonym to a word */
  248. int add_synonym(str,wrd)
  249.   char *str; int wrd;
  250. {
  251.     curwrd = wrd;
  252.     return (tenter(words,str));
  253. }
  254.  
  255. /* getword - get a word from an object field */
  256. int getword(off)
  257.   int off;
  258. {
  259.     return ((data[off] & 0xFF) | (data[off+1] << 8));
  260. }
  261.  
  262. /* putword - put a word into an object field */
  263. putword(off,dat)
  264.   int off,dat;
  265. {
  266.     data[off] = dat;
  267.     data[off+1] = dat >> 8;
  268. }
  269.  
  270. /* getbyte - get a byte from an object field */
  271. int getbyte(off)
  272.   int off;
  273. {
  274.     return (data[off]);
  275. }
  276.  
  277. /* putbyte - put a byte into an object field */
  278. putbyte(off,dat)
  279.   int off,dat;
  280. {
  281.     data[off] = dat;
  282. }
  283.  
  284. /* output - output the binary data structures */
  285. output()
  286. {
  287.     int woff,wsize;    /* word table offset and size */
  288.     int ooff,osize;    /* object table offset and size */
  289.     int aoff,asize;    /* action table offset and size */
  290.     int toff,tsize;    /* word type table offset and size */
  291.     int voff,vsize;    /* variable table offset and size */
  292.     int soff,ssize;    /* save area offset and size */
  293.     int dsize;        /* data size without dictionary */
  294.     int dbase,cbase,size,mblk,dblk,i;
  295.  
  296.     /* make sure the adventure id information is present */
  297.     if (aname[0] == 0) {
  298.     xerror("no adventure identification information");
  299.     strcpy(aname,"ADVENTURE");
  300.     aversion = 0;
  301.     }
  302.  
  303.     /* pad the remainder of this message block */
  304.     while (msgoff & 0x007F)
  305.     { ad_putc('\0'); ad_putc('\0'); ad_putc('\0'); ad_putc('\0'); msgoff++; }
  306.  
  307.     /* save the size of the data area before the dictionary */
  308.     dsize = dptr;
  309.  
  310.     /* insert the vocabulary into the data array */
  311.     woutput(words->tr_root);
  312.  
  313.     /* compute table offsets */
  314.     woff = 0;            wsize = tentries(words) * 2 + 2;
  315.     toff = woff + wsize; tsize = wcnt;
  316.     ooff = toff + tsize; osize = ocnt * 2 + 2;
  317.     aoff = ooff + osize; asize = acnt * 2 + 2;
  318.     voff = aoff + asize; vsize = vcnt * 2 + 2;
  319.     dbase = voff + vsize;
  320.     cbase = dbase + dptr;
  321.  
  322.     /* compute the resident structure size */
  323.     size = wsize+tsize+osize+asize+vsize+dptr+cptr;
  324.  
  325.     /* set the save area parameters */
  326.     soff = voff; ssize = vsize + dsize;
  327.  
  328.     /* compute the first block for message text */
  329.     mblk = 1;
  330.     dblk = (int)(ad_foff >> 9);
  331.  
  332.     /* output the word table */
  333.     word_out(tentries(words));
  334.     wtoutput(words->tr_root);
  335.  
  336.     /* output the word type table */
  337.     for (i = 1; i <= wcnt; i++)
  338.     byte_out(wtable[i]);
  339.  
  340.     /* output the object table */
  341.     word_out(ocnt);
  342.     for (i = 1; i <= ocnt; i++) {
  343.     if (otable[i] == NIL)
  344.         undef_object(i);
  345.     word_out(otable[i]);
  346.     }
  347.  
  348.     /* output the action table */
  349.     word_out(acnt);
  350.     for (i = 1; i <= acnt; i++)
  351.     word_out(atable[i]);
  352.  
  353.     /* beginning of saveable data */
  354.  
  355.     /* output the variable table */
  356.     word_out(vcnt);
  357.     for (i = 1; i <= vcnt; i++)
  358.     word_out(NIL);
  359.  
  360.     /* output the data space */
  361.     for (i = 0; i < dptr; )
  362.     byte_out(data[i++]);
  363.  
  364.     /* end of saveable data */
  365.  
  366.     /* output the code space */
  367.     for (i = 0; i < cptr; )
  368.     byte_out(code[i++]);
  369.  
  370.     /* output the file header */
  371.     ad_seek(0L);
  372.     word_out(size);    /* resident structure size */
  373.     str_out("ADVSYS",6);/* magic information */
  374.     word_out(VERSION);    /* data structure version number */
  375.     str_out(aname,18);    /* adventure name */
  376.     word_out(aversion);    /* adventure version number */
  377.     word_out(woff);    /* word table offset */
  378.     word_out(toff);    /* word type table offset */
  379.     word_out(ooff);    /* object table offset */
  380.     word_out(aoff);    /* action table offset */
  381.     word_out(voff);    /* variable table offset */
  382.     word_out(dbase);    /* base of data */
  383.     word_out(cbase);    /* base of code */
  384.     word_out(dblk);    /* first data block */
  385.     word_out(mblk);    /* first message text block */
  386.     word_out(h_init);    /* initialization code */
  387.     word_out(h_update);    /* update code */
  388.     word_out(h_before);    /* before handler code */
  389.     word_out(h_after);    /* after handler code */
  390.     word_out(h_error);    /* error handling code */
  391.     word_out(soff);    /* save area offset */
  392.     word_out(ssize);    /* save area size */
  393.  
  394.     /* show statistics */
  395.     printf("[ words:      %d ]\n",tentries(words));
  396.     printf("[ word types: %d ]\n",wcnt);
  397.     printf("[ objects:    %d ]\n",ocnt);
  398.     printf("[ actions:    %d ]\n",acnt);
  399.     printf("[ variables:  %d ]\n",vcnt);
  400.     printf("[ data:       %d ]\n",dsize);
  401.     printf("[ code:       %d ]\n",cptr);
  402.     printf("[ dictionary: %d ]\n",dptr-dsize);
  403.     printf("[ text:       %ld ]\n",(long) msgoff * 4L);
  404.     printf("[ save area:  %d ]\n",ssize);
  405.     printf("[ errors:     %d ]\n",errcount);
  406.     advpause();
  407. }
  408.  
  409. /* woutput - output the word data */
  410. woutput(node)
  411.   TNODE *node;
  412. {
  413.     int wnum,wrd;
  414.  
  415.     if (node) {
  416.     woutput(LLINK(node));
  417.     wnum = WORD(node);
  418.     wrd = WORD(node) = dalloc(strlen(KEY(node))+3);
  419.     putword(wrd,wnum);
  420.     strcpy(data+wrd+2,KEY(node));
  421.     if (wtable[wnum] == WT_UNKNOWN)
  422.         printf("Type of word %s is unknown\n",KEY(node));
  423.     woutput(RLINK(node));
  424.     }
  425. }
  426.  
  427. /* wtoutput - output the word table */
  428. wtoutput(node)
  429.   TNODE *node;
  430. {
  431.     if (node) {
  432.     wtoutput(LLINK(node));
  433.     word_out(WORD(node));
  434.     wtoutput(RLINK(node));
  435.     }
  436. }
  437.  
  438. /* undef_object - complain about an undefined object */
  439. undef_object(n)
  440.   int n;
  441. {
  442.     char msg[100];
  443.     SYMBOL *sym;
  444.  
  445.     for (sym = symbols; sym != NULL; sym = sym->s_next)
  446.     if (sym->s_type == ST_OBJECT && n == sym->s_value) {
  447.         sprintf(msg,"Object %s is undefined",sym->s_name);
  448.         xerror(msg);
  449.         break;
  450.     }
  451. }
  452.  
  453. /* str_out - output a string */
  454. str_out(str,len)
  455.   char *str; int len;
  456. {
  457.     while (len--)
  458.     byte_out(*str++);
  459. }
  460.  
  461. /* word_out - output a word */
  462. word_out(dat)
  463.   int dat;
  464. {
  465.     byte_out(dat);
  466.     byte_out(dat >> 8);
  467. }
  468.  
  469. /* byte_out - output a byte */
  470. byte_out(dat)
  471.   int dat;
  472. {
  473.     ad_putc((~dat - 30) & 0xFF);
  474. }
  475.  
  476. /* oenter - enter an object into the symbol table */
  477. int oenter(name)
  478.   char *name;
  479. {
  480.     SYMBOL *sym;
  481.  
  482.     if (sym = sfind(name)) {
  483.     if (sym->s_type != ST_OBJECT)
  484.         error("Not an object");
  485.     return (sym->s_value);
  486.     }
  487.     if (ocnt < OMAX) {
  488.         senter(name,ST_OBJECT,++ocnt);
  489.         otable[ocnt] = NIL;
  490.     }
  491.     else
  492.     error("too many objects");
  493.     return (ocnt);
  494. }
  495.  
  496. /* ofind - find an object in the symbol table */
  497. int ofind(name)
  498.   char *name;
  499. {
  500.     SYMBOL *sym;
  501.  
  502.     if (sym = sfind(name)) {
  503.     if (sym->s_type != ST_OBJECT)
  504.         return (NIL);
  505.     return (sym->s_value);
  506.     }
  507.     return (NIL);
  508. }
  509.  
  510. /* aenter - enter an action into the symbol table */
  511. int aenter(name)
  512.   char *name;
  513. {
  514.     SYMBOL *sym;
  515.  
  516.     if (sym = sfind(name)) {
  517.     if (sym->s_type != ST_ACTION)
  518.         error("Not an action");
  519.     return (sym->s_value);
  520.     }
  521.     if (acnt < AMAX) {
  522.         senter(name,ST_ACTION,++acnt);
  523.         atable[acnt] = NIL;
  524.     }
  525.     else
  526.     error("too many actions");
  527.     return (acnt);
  528. }
  529.  
  530. /* venter - enter a variable into the symbol table */
  531. int venter(name)
  532.   char *name;
  533. {
  534.     SYMBOL *sym;
  535.  
  536.     if (sym = sfind(name)) {
  537.     if (sym->s_type != ST_VARIABLE)
  538.         error("Not a variable");
  539.     return (sym->s_value);
  540.     }
  541.     senter(name,ST_VARIABLE,++vcnt);
  542.     return (vcnt);
  543. }
  544.  
  545. /* penter - enter a property into the symbol table */
  546. int penter(name)
  547.   char *name;
  548. {
  549.     SYMBOL *sym;
  550.  
  551.     if (sym = sfind(name)) {
  552.     if (sym->s_type != ST_PROPERTY)
  553.         error("Not a property");
  554.     return (sym->s_value);
  555.     }
  556.     senter(name,ST_PROPERTY,++pcnt);
  557.     return (pcnt);
  558. }
  559.  
  560. /* center - enter a constant into the symbol table */
  561. center(name,value)
  562.   char *name; int value;
  563. {
  564.     if (sfind(name)) {
  565.     error("Already defined");
  566.     return;
  567.     }
  568.     senter(name,ST_CONSTANT,value);
  569. }
  570.  
  571. /* sfind - find a symbol in the symbol table */
  572. SYMBOL *sfind(name)
  573.   char *name;
  574. {
  575.     SYMBOL *sym;
  576.  
  577.     for (sym = symbols; sym != NULL; sym = sym->s_next)
  578.     if (strcmp(name,sym->s_name) == 0)
  579.         break;
  580.     return (sym);
  581. }
  582.  
  583. /* senter - enter a symbol into the symbol table */
  584. SYMBOL *senter(name,type,value)
  585.   char *name; int type,value;
  586. {
  587.     SYMBOL *sym;
  588.  
  589.     if ((sym = (SYMBOL *)malloc(sizeof(SYMBOL))) == NULL)
  590.     advfatal("out of memory");
  591.     sym->s_name = save(name);
  592.     sym->s_type = type;
  593.     sym->s_value = value;
  594.     sym->s_next = symbols;
  595.     symbols = sym;
  596.     return (sym);
  597. }
  598.  
  599. /* frequire - fetch a token and check it */
  600. frequire(rtkn)
  601.   int rtkn;
  602. {
  603.     require(token(),rtkn);
  604. }
  605.  
  606. /* require - check for a required token */
  607. require(tkn,rtkn)
  608.   int tkn,rtkn;
  609. {
  610.     char msg[100];
  611.     if (tkn != rtkn) {
  612.     sprintf(msg,"Expecting %s",t_names[rtkn]);
  613.     error(msg);
  614.     }
  615. }
  616.  
  617. /* save - allocate memory for a string */
  618. char *save(str)
  619.   char *str;
  620. {
  621.     char *new;
  622.  
  623.     if ((new = malloc(strlen(str)+1)) == NULL)
  624.     advfatal("out of memory");
  625.     strcpy(new,str);
  626.     return (new);
  627. }
  628.  
  629. /* match - compare a string with the current token */
  630. int match(str)
  631.   char *str;
  632. {
  633.     return (strcmp(str,t_token) == 0);
  634. }
  635.